<?php
/**
 * Created by b17
 * 2/29/12 6:22 PM
 */


namespace Managers;

class CommentsRating extends BaseManager
{
    const TABLE = '\Catalog\CommentRating';
    protected $__table = self::TABLE;
    private $_ip;

    public function __construct()
    {
        parent::__construct();
        $this->_ip = ip2long($_SERVER['REMOTE_ADDR']);
    }

    protected function createQueryBuilder()
    {
        $qb = parent::createQueryBuilder()
            ->select('cr, c')
            ->from($this->__table, 'cr')
            ->join('cr.comment', 'c');
        return $qb;
    }

    public function addRatings($comments)
    {
        if (!count($comments)) {
            return $comments;
        }
        $ids = self::rebuildArray($comments);
        $qb = $this->createQueryBuilder()
            ->select('cr, partial c.{id}');
        $qb->andWhere($qb->expr()->in('c.id', $ids));
        $res = $qb->getQuery()->getArrayResult();
        $res = $this->injectRating($comments, $res);
        return $res;
    }

    private function injectRating($comments, $ratings)
    {
        foreach ($comments as &$comment) {
            $mark = 0;
            $votable = true;
            foreach ($ratings as $rating) {

                if ($this->isRatingToComment($rating, $comment)) {
                    $mark += $rating['value'];
                    if ($votable) {
                        $votable = $rating['ip'] != $this->_ip;
                    }
                }
            }
            if (count($comment['children'])) {
                $comment['children'] = $this->injectRating($comment['children'], $ratings);
            }
            $comment['rating'] = $mark;
            $comment['votable'] = $votable;
        }
        return $comments;
    }

    private function isRatingToComment($rating, $comment)
    {
        return $rating['comment']['id'] == $comment['id'];
    }

    public static function rebuildArray($comments)
    {
        $ids = Utils::rebuildArray($comments);
        foreach ($comments as $comment) {
            if (count($comment['children'])) {
                $ids = array_merge($ids, self::rebuildArray($comment['children']));
            }
        }
        return $ids;
    }

    public function rate($commentId, $value)
    {
        if ($this->isAvailable($commentId)) {
            $entity = new \Catalog\CommentRating();
            $commentRef = $this->_em->getReference(Comments::TABLE, $commentId);
            $entity->setComment($commentRef);
            $entity->setValue($value);
            $entity->setIp($this->_ip);
            $this->_em->persist($entity);
            $this->flush();
            return $entity;
        }
        return false;
    }

    public function isAvailable($commentId)
    {
        $qb = $this->createQueryBuilder()
            ->select('partial cr.{id}')
            ->andWhere('c.id = :comment')->setParameter('comment', $commentId)
            ->andWhere('cr.ip = :ip')->setParameter('ip', $this->_ip);
        $res = $qb->getQuery()->getArrayResult();
        return count($res) ? false : true;
    }

    public function getRating($commentId)
    {
        $qb = $this->createQueryBuilder()
            ->select('sum(cr.value) as total')
            ->andWhere('c.id = :comment')->setParameter('comment', $commentId)
            ->addGroupBy('c.id');
        $res = $qb->getQuery()->getArrayResult();
        return $res[0]['total'];
    }
}
